#include "Spawner.h"


Spawner::Spawner(Vector3 initial, int freeList_space) : position(initial)
{
	freeList = new EntityFreeList(freeList_space);
	mesh = new OBJMesh(MESHDIR"cube.obj"); //maybe it'd be better to have a mesh manager? this would allow to change the mesh at will 
	active = false;
}


Spawner::~Spawner()
{
	delete freeList;
}

/* Method used to first retrieve from freelist and then spawn into the game
* Return: Spawned objected connected to physics and renderer
* Parameters: void
* Author: Borja
*/
GameEntity* Spawner::spawn(int type)
{
	//basic pseudo-randomness
	std::random_device generator;
	std::uniform_int_distribution<int> distribution(-7, 7);


	int displacement = distribution(generator);
	int zDisp = distribution(generator);
	
	Vector3 spawnPoint = Vector3(position.x + (200 * displacement), position.y + 200, position.z + (50 * zDisp));

	// --------- Added by Monica ---------------- //
	spawnPoint.z /= VoxelChunck::getZChunckSize();
	float height = terrain->getHeightAtPosition(spawnPoint);
	spawnPoint.y = height;
	spawnPoint.z *= VoxelChunck::getZChunckSize();
	//Vector3 spawnPoint = position;
	// ----------------------------------------- //

	GameEntity*g = freeList->GetNewObject();
	g->GetRenderNode().SetMesh(mesh);
	g->GetRenderNode().SetModelScale(Vector3(25, 25, 25));
	g->GetRenderNode().SetBoundingRadius(100);
	// ------ Added by Monica ---- ///
	g->GetRenderNode().SetTransform(Matrix4::Translation(spawnPoint));
	// --------------------------- //


	g->GetPhysicsNode().SetPosition(spawnPoint);
	g->GetPhysicsNode().SetLinearVelocity(Vector3(0, 0, terrain->LINEAR_VELOCITY_Z));
	g->GetPhysicsNode().SetInverseInertia(InertialMatrixHelper::createSphereInvInertial(1.0f, 100));
	g->GetPhysicsNode().SetInverseMass(1.0f);
	g->GetPhysicsNode().SetUseLinearDamping(false);
	g->GetPhysicsNode().SetUseGravity(false);
	
	
	switch (type)
	{
		case 1:
			g->GetRenderNode().SetColour(Vector4(0.2, 0.8, 0.2, 1));
			g->GetPhysicsNode().SetCollisionVolume(new CollisionOBB(Vector3(25, 25, 25), BUFF));
			break;
		case 2:
			g->GetRenderNode().SetColour(Vector4(0.8, 0.2, 0.8, 1));
			g->GetPhysicsNode().SetCollisionVolume(new CollisionOBB(Vector3(25, 25, 25), FLY_BUFF));
			break;
		case 3:
			g->GetRenderNode().SetColour(Vector4(0.2, 0.2, 0.8, 1));
			g->GetPhysicsNode().SetCollisionVolume(new CollisionOBB(Vector3(25, 25, 25), RUSH_BUFF));
			break;
		case 4:
			g->GetRenderNode().SetColour(Vector4(0.8, 0.2, 0.2, 1));
			g->GetPhysicsNode().SetCollisionVolume(new CollisionOBB(Vector3(25, 25, 25), DEBUFF));
			break;
	}

	g->ConnectToSystems();
	return g;
}


/* Method used to handle the return and despawning of the object
* Return: void
* Parameters: object to be despawned
* Author: Borja
*/
void Spawner::despawn(GameEntity* obj)
{
	obj->DisconnectFromSystems();
	freeList->DiscardObject(obj);
}